package proxy;

import java.util.ArrayList;

import simulation.Simulator;

public class ShortestPathRoutingDirectDownload extends ShortestPathRouting {

	// cite: Modeling and performance analysis of BitTorrent-like peer-to-peer
	// networks, SIGCOMM'04, vol. 34, issue 4, doi: 10.1145/1030194.1015508
	private final int maxOpenConnections = 40;

	public ShortestPathRoutingDirectDownload(Simulator simulator) {
		super(simulator);
	}

	@Override
	public void routeUnit(ArrayList<ServerNode> route, int id) {
		// 1) verbinde direkt zum letzten knoten
		// 2) wenn ein link schon vorhanden ist, nutze den sonst mache einen
		// neuen link auf (neues outgoing)
		// 3) nach dem transfer wird der link wieder geschlossen
		if (route.size() == 1)
			return; // unit is already local
		String s, delim = "";
		s = "Routing u" + id;
		for (int i = route.size() - 1; i >= 0; i--) {
			s = s + delim + " S" + route.get(i).getId();
			delim = " ->";
		}
		simulator.log(s);

		ServerNode lastServer = route.get(route.size() - 1);
		boolean copy = true;
		UnitContainer uc = lastServer.searchPresentUnit(id);

		ServerNode requester = route.get(0);
		// now we need to transfer from sender to requester
		// 1) check if there is already a link
		if (requester.containsTarget(lastServer)) {
			if (lastServer.migrateUnitTo(uc.getVideoUnit(),
					requester.getLinkTo(lastServer), copy)) {
				route.clear();
			}
		} else {
			//2) create link as long connections can be made
			if (requester.getLinks().size() < maxOpenConnections) {
				double datarate = requester.getLinks().get(0).getDatarate();
				//unidirectional link is enough
				lastServer.getLinks().add(new Link(requester, datarate));
				lastServer.getOutgoingUnits().add(new ArrayList<Migration>());
				Link newLink = lastServer.getLinkTo(requester);
				if (lastServer.migrateUnitTo(uc.getVideoUnit(), newLink, copy)) {
					route.clear();
					int linkid = lastServer.getLinks().indexOf(newLink);
					lastServer.getOutgoingUnits().remove(linkid);
					lastServer.getLinks().remove(newLink);
				} 
			}
		}
	}

}
